using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace Serpis
{
	//**	...Con la AYUDA de A.Farina
	public class Persister 
	{
		/// <summary>
		/// Guarda en la base de datos el objeto indicado.
		/// Para ello busca por reflexión las propiedades decoradas mediante "FieldAttribute" y "PrimaryKeyAttribute"
		/// </summary>
		public void Save(object model)
		{
			//**	Consulta que haremos a la base de datos, ya sea un INSERT o un UPDATE
			bool executeSQL = false;
			//**	Extraemos el nombre de la tabla de la que tenemos que consultar
			string nombreTabla= model.GetType().Name.ToLower();
			//**	Creamos un dbCommand para manejar la Base de Datos
			IDbCommand dbCommand= AppDbConnection.Instance.DbConnection.CreateCommand();
			
			//**	Creamos una lista con las propiedades
			List<string> campos = new List<string>();
			string clavePrimaria = null;
		
			Type tipodelModelo = model.GetType();
			
			//**	Con el siguiente foreach crearemos dinamicamente los parametros oportunos en función del modelo recibido
			foreach(PropertyInfo propertyInfo in tipodelModelo.GetProperties())
			{	
				string nombrePropiedad = propertyInfo.Name.ToLower();
				object value = propertyInfo.GetValue(model, null);
				
				IDbDataParameter dbDataParameter= dbCommand.CreateParameter();
				dbDataParameter.ParameterName= nombrePropiedad;
				dbDataParameter.Value= value;
				dbCommand.Parameters.Add(dbDataParameter);
				
				//**	Si la propiedad está decorada con FieldAttributes, la añadimos a la lista
				if(propertyInfo.IsDefined(typeof(FieldAttribute), false))
				{
					campos.Add(nombrePropiedad);
					continue;
				}
				
				if(propertyInfo.IsDefined(typeof(PrimaryKeyAttribute), false))
				{
					clavePrimaria = nombrePropiedad;
					if(value == null || value=="" || Convert.ToInt64(value)==0)
					{
						executeSQL = true;
					}
					else
					{
						executeSQL = false;
					}
				}
			}
			if(clavePrimaria == null)
			{
				Console.WriteLine("NO EXISTE LA CLAVE PRIMARIA");
			}
			
			string consultaSQL;
			
			if(executeSQL)
			{
				consultaSQL= insertString(nombreTabla, campos);
			}
			else
			{
				consultaSQL= updateString(nombreTabla, campos, clavePrimaria);
			}
			Console.WriteLine(consultaSQL);
			dbCommand.CommandText= consultaSQL;
			if(dbCommand.ExecuteNonQuery() < 1)
			{
				Console.WriteLine("SQL INCORRECTO");
			}
			
		}
		//**	Recibe un Type y un Id y devuelve los datos de la tabla consultada como un objeto.
		public object Load(Type type, object id)
		{
			//**	Si el id es null, es por que no habia nada seleccionado en miTreeView
			if(id==null)
			{
				return null;
			}
			
			//**	Extraemos el nombre de la tabla de la que tenemos que consultar
			string nombreTabla= type.Name.ToLower();
			//**	Creamos un dbCommand para manejar la Base de Datos
			IDbCommand dbCommand= AppDbConnection.Instance.DbConnection.CreateCommand();
		
			object model = Activator.CreateInstance(type);
			
			dbCommand.CommandText = "SELECT * FROM "+nombreTabla+" WHERE id="+id+";";
			IDataReader dataReader = dbCommand.ExecuteReader();
			if(dataReader.Read())
			{
				foreach(PropertyInfo propertyInfo in type.GetProperties())
				{
					object value = dataReader[propertyInfo.Name.ToLower()];
					if(value is DBNull)
					{
						value=null;
					}
					propertyInfo.SetValue(model, value, null);
				}
			}
			dataReader.Close();
			return model;	
		}
		//**	Devuelve un string con la consulta UPDATE que debemos actualizar segun lo valores recogidos en la Lista que recibe.
		private string updateString(string nombreTabla, List<string> campos, string clavePrimaria) 
		{
			for(int i=0 ;i<campos.Count ;i++)
			{
				campos[i]= campos[i]+"=?"+campos[i];
			}			
			string consulta= "UPDATE "+nombreTabla+" SET "+string.Join(",", campos.ToArray())+" WHERE id=?"+clavePrimaria+";";		
			return consulta;
		}
		//**	Devuelve un string con la consulta UPDATE que debemos actualizar segun lo valores recogidos en la Lista que recibe.
		private string insertString(string table, List<string> fields) 
		{
			string consulta= "INSERT INTO "+table+" ("+string.Join(",",fields.ToArray())+") VALUES (";
			
			for(int i=0 ;i<fields.Count ;i++)
				fields[i]="?"+fields[i];
			
			consulta+= string.Join(",",fields.ToArray())+");";
			return consulta;
		}
	}
}
